package org.hxzon.util;

import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class ScheduleUtil {

    /**
     * 
     * @param endTime millisecond
     */
    public static ScheduledFuture<?> schedule(Runnable run, long initDelay, TimeUnit initDelayTimeUnit, //
            long endTime, long period, TimeUnit periodTimeUnit, ScheduledExecutorService executor) {
        if (endTime > System.currentTimeMillis() + periodTimeUnit.toMillis(period)) {
            return executor.schedule(new Task(executor, run, endTime, period, periodTimeUnit), //
                    initDelay, initDelayTimeUnit);
        }
        return null;
    }

    public static void awaitShutdown(long endTime, ScheduledExecutorService executor) {
        try {
            long timeout = endTime - System.currentTimeMillis();
            executor.awaitTermination(timeout, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private static class Task implements Runnable {
        private ScheduledExecutorService executor;
        private long endTime;
        private long period;
        private TimeUnit periodTimeUnit;
        private Runnable run;

        public Task(ScheduledExecutorService executor, Runnable run,//
                long endTime, long period, TimeUnit periodTimeUnit) {
            this.executor = executor;
            this.run = run;
            this.endTime = endTime;
            this.period = period;
            this.periodTimeUnit = periodTimeUnit;
        }

        public void run() {
            run.run();
            if (endTime > System.currentTimeMillis() + periodTimeUnit.toMillis(period)) {
                executor.schedule(this, period, periodTimeUnit);
            }
        }
    }

    //test
    public static void main(String[] args) {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
        Date endTime = DateFormatUtil.parse("2013-11-28,10:26:00", "yyyy-MM-dd,HH:mm:ss");
        ScheduleUtil.schedule(new Runnable() {
            public void run() {
                System.out.println(DateFormatUtil.formatToSecond());
            }
        }, 2, TimeUnit.SECONDS, endTime.getTime(), 500, TimeUnit.MILLISECONDS, executor);
        ScheduleUtil.awaitShutdown(endTime.getTime() + 2000, executor);//how to stop all thread?
    }
}
